﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Shop.Base.Entity;
using Shop.Base.Entity.Assist;
using Shop.Base.Entity.AutoMapperConfig;
using Shop.Base.Entity.View;
using Shop.Base.Interface;
using Shop.Entity;
using Shop.Tools;
using Shop.Tools.Util;
using Shop.Web.Filter;
using Shop.Web.Models;

namespace Shop.Web.Controllers
{
    public class LoginController : Controller
    {
        private readonly ISystemUser iuser;
        private readonly IMapper mapper;
        private readonly ISystemUserRole userRole;
        private readonly ISystemRoleFunction roleFunction;
        public LoginController(ISystemUser _iuser, IMapper _mapper, ISystemUserRole _userRole, ISystemRoleFunction _roleFunction)
        {
            iuser = _iuser;
            mapper = _mapper;
            userRole = _userRole;
            roleFunction = _roleFunction;
        }
        [NoSign]
        public IActionResult Index()
        {
            var cookie = HttpContext.Request.Cookies.TryGetValue("remindMe", out string account);
            ViewData["Account"] = cookie ? account : (TempData["Account"] != null && !TempData["Account"].ToString().IsNullOrEmpty() ? TempData["Account"] : "");
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        [NoSign]
        public IActionResult Login(string account, string pwd, string checkCode, string remindMe, string vCode)
        {
            try
            {
                //StaticConst.log.Info(HttpContext.Request.Host.Host);
                TempData["Account"] = account;
                if (ModelState.IsValid)
                {
                    if (account.IsNullOrEmpty()) throw new Exception("请检查账号");
                    if (pwd.IsNullOrEmpty()) throw new Exception("请检查密码");
                    if (checkCode.IsNullOrEmpty() || vCode.IsNullOrEmpty()) throw new Exception("请检查验证码");
                    string chkcode;
                    try { chkcode = Tools.Util.Tools.Decode(vCode, GlobalConst.CheckCodeKey); } catch (Exception e) { chkcode = ""; }
                    if (checkCode.ToLower() != chkcode.ToLower()) throw new Exception("验证码错误");
                    var user = iuser.Login(new UserLogin { Account = account, Password = pwd });
                    if (user == null) throw new Exception("账号不存在错误");
                    if (!user.IsLogin) throw new Exception("账号已禁用");
                    var pwds = Tools.Util.Tools.MD5Encrypt(pwd);
                    if (pwds != user.Passwd) throw new Exception("密码错误");
                    HttpContext.Session.Set(SessionKeys.UserId, user.Id);
                    HttpContext.Session.Set(SessionKeys.UserName, user.Name);
                    if (!user.IsNormal)
                    {
                        var roleIds = userRole.GetList(user.Id);
                        if (roleIds.Any())
                        {
                            var roleFunctions = roleFunction.GetUserRoleFunction(roleIds.Select(x => x.RoleId).ToList());
                            if (roleFunctions.Any())
                            {
                                var roleMenus = RoleMenus(roleFunctions);
                                HttpContext.Session.Set(SessionKeys.Authority, roleMenus);
                                HttpContext.Session.Set(SessionKeys.UserMenu, roleFunctions);
                            }
                            else
                            {
                                user.IsNormal = true;
                            }
                        }
                        else
                        {
                            user.IsNormal = true;
                        }
                    }
                    var comUser = mapper.Map<SystemUserPo, ComUser>(user);
                    HttpContext.Session.Set(SessionKeys.UserInfo, comUser);
                    #region 暂时不用 【框架自带】

                    ////用户标识 
                    // var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
                    //identity.AddClaim(new Claim(ClaimTypes.Sid,user.Name));
                    //identity.AddClaim(new Claim(ClaimTypes.Name,user.Name));
                    //identity.AddClaim(new Claim(ClaimTypes.NameIdentifier,user.Id.ToString()));
                    //await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(identity));

                    #endregion
                    //记住账号
                    if (!remindMe.IsNullOrEmpty())
                        HttpContext.Response.Cookies.Append("remindMe", account);
                    return RedirectToAction("Index", "Home");
                }
                throw new Exception("无效的请求");
            }
            catch (Exception e)
            {
                Tools.StaticConst.log.Error(e);
                TempData["SysMsg"] = e.Message;
                return RedirectToAction("Index");
            }
        }

        //获取验证码
        [NoSign]
        [HttpGet]
        public IActionResult GetCode()
        {
            try
            {
                var code = new CheckCode().GetNextCode(out var codes);
                //验证码加密输出
                var chkCode = Tools.Util.Tools.Encode(codes, GlobalConst.CheckCodeKey);
                return Json(new ResultModel { data = new { img = "data:image/jpeg;base64," + code, vCode = chkCode }, code = OperationResultType.Success, error_msg = "", success = true });
            }
            catch (Exception e)
            {
                return Json(new ResultModel { data ="", code = OperationResultType.Success, error_msg = e.Message, success = false });
            } 
        }

        //退出登录
        [HttpGet]
        public IActionResult Logout()
        {
            HttpContext.Session.Remove(SessionKeys.UserId);
            HttpContext.Session.Remove(SessionKeys.UserName);
            HttpContext.Session.Remove(SessionKeys.UserInfo);
            HttpContext.Session.Remove(SessionKeys.Authority);
            HttpContext.Session.Remove(SessionKeys.UserMenu);

            #region 暂时不用 【框架自带】

            //await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

            #endregion
            return RedirectToAction("Index", "Home");
        }

        private List<SystemMenuHelp> RoleMenus(List<UserRoleFunction> list)
        {
            //所有菜单
            var allMenu = list.Where(x => x.IsButton == false).ToList();
            var sourceList = new List<SystemMenuHelp>();
            var targetList = new List<SystemMenuHelp>();
            if (allMenu.Any())
            {
                
                sourceList = allMenu.Select(x => new SystemMenuHelp
                {
                    MenuParentId = x.ParentId.HasValue ? x.ParentId.Value + "" : "",
                    MenuId = x.MenuId + "",
                    MenuName = x.MemuName,
                    MenuIcon = x.MenuIcons,
                    ActionName = x.ActionStr,
                    AreaName = x.AreaStr,
                    ControllerName = x.ControllerStr,
                    MenuNum = x.IndexNum
                }).ToList();
                list.Where(x => x.IsButton).ToList().ForEach(x =>
                {
                    var pid = x.ParentId.HasValue ? x.ParentId.Value + "" : "";
                    if (!sourceList.Exists(c => c.MenuParentId == pid && c.MenuId == $"{x.MenuId}"))
                    {
                        sourceList.Add(new SystemMenuHelp
                        {
                            MenuParentId = pid,
                            MenuId = x.MenuId + "",
                            MenuName = x.MemuName,
                            MenuIcon = x.MenuIcons,
                            ActionName = x.ActionStr,
                            AreaName = x.AreaStr,
                            ControllerName = x.ControllerStr,
                            MenuNum = x.IndexNum
                        });
                    }
                });
                LoadTree(sourceList, targetList, "");
            }
            return targetList;
        }

        private List<SystemMenuHelp> LoadTree(List<SystemMenuHelp> source, List<SystemMenuHelp> target, string parentId)
        {
            foreach (var item in source.Where(x => x.MenuParentId == parentId))
            {
                var childNode = source.Where(x => x.MenuParentId == item.MenuId).ToList();
                if (childNode.Any())
                {
                    LoadTree(source, item.Child, item.MenuId);
                }
                target.Add(item);
            }
            return target;
        }
    }
}